package com.example.controller;

import com.example.bean.DownFile;
import com.example.bean.Myfile;
import com.example.service.Impl.MyfileServiceImpl;
import com.example.util.R;
import com.github.pagehelper.PageInfo;
import jdk.nashorn.internal.parser.JSONParser;
import jdk.nashorn.internal.runtime.JSONListAdapter;
import org.apache.ibatis.jdbc.Null;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.ModelAndView;


import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLConnection;
import java.net.URLEncoder;
import java.nio.channels.FileChannel;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;

/**
 * Created by 殇 on 2022/7/21.
 */
@CrossOrigin("*")
@Controller
public class FileUploadController {

    @Autowired(required = true)
    private MyfileServiceImpl myfileServiceImpl;

//    默认文件存储地址
    private static String filepath = "D:\\myfile";

    private Long newMyfiletime;
    private int init = 1;
//    解决文件下载中断，—第一次请求是正常传输参数的，大约传输5KB左右的数据就会重复出现—
//    报错内容是—注意是在下载过程中发生的—“在接口的请求信息中找不到方法与方法对应的参数”
    static Myfile DownFile;


//   首页
    @RequestMapping("/Index")
    public ModelAndView Index(Map<String,Object>  map){

        ModelAndView modelAndView = new ModelAndView("index");
        map.put("x","Index");

        modelAndView.addAllObjects(map);
        return modelAndView;

    }

    //文件上传页面
    @ResponseBody
    @RequestMapping("/fileUpload")
    public ModelAndView fileUpload(){

        return new ModelAndView("pages/upload");

    }


//    @ResponseBody
//    @RequestMapping("/Test")
//    初始化数据库
    public String initialization() throws IOException {

        System.out.println("————initialization(初始化 down_file)————");

        myfileServiceImpl.DelDownFile();

        File file = new File(filepath);

        if(file.exists()){
            File[] files = file.listFiles();

            for(int i = 0;i < files.length;i++){
                File f = files[i];
                if(f.isFile()){
                    DownFile downFile = new DownFile();
                    downFile.setFilename(f.getName().substring(0,f.getName().indexOf(".")));
                    downFile.setFilepath(f.getPath());

                    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-dd-MM HH:mm:ss");
                    downFile.setFiletime(sdf.format(f.lastModified()));
                    downFile.setSize(Float.parseFloat(Long.toString(f.length()))/1048576);


                    URLConnection connection = f.toURL().openConnection();
                    downFile.setType(connection.getContentType());

                    myfileServiceImpl.DownSave(downFile);

                    System.out.println(downFile.toString());
                }

            }
        }

        return file.toString();
    }



//    文件上传功能
    @RequestMapping("/UploadFile")
    @ResponseBody
    public R UploadFile(MultipartFile file)throws IOException{

        init = 1;

//        System.out.println(file.getOriginalFilename());
//        System.out.println(file.getName());

        file.getInputStream();
        file.getBytes();

//        创建文件目录
        File F = new File(filepath);
        if(!F.exists()){
            F.mkdir();
        }

//        创建文件
        File file1 = new File(filepath+"\\"+file.getOriginalFilename());



        System.out.println(filepath+"\\"+file.getOriginalFilename());

//        判断当前文件是否已存在
        if(file1.exists()){
            System.out.println("文件已存在");
//            如果存在就备份当前文件
            this.filecopy(file1.getPath(),file.getOriginalFilename());

        }else{
//            如果不想存在就创建它
            try{
                file1.createNewFile();
            }catch (IOException e){
                e.printStackTrace();
            }

        }



//        创建文件流
        FileOutputStream Fout = new FileOutputStream(file1);

        try{

//            将要上传的文件以二进制写入上面的创建的文件中
            Fout.write(file.getBytes());


        }catch (IOException e){
            e.printStackTrace();
        }
        Fout.close();


//        上传数据库
        Myfile Myfile = new Myfile();

        Myfile.setFilename(file.getOriginalFilename());
        Myfile.setFilepath(file1.getPath());
        Myfile.setType(file.getContentType());
        Myfile.setFiletime(LocalDateTime.now().toString());
        Myfile.setSize(Float.parseFloat(Long.toString(file.getSize()))/1048576);
        myfileServiceImpl.save(Myfile);


        return R.ok();
    }



//    文件查看
    @ResponseBody
    @RequestMapping("/ViewFile")
    public ModelAndView ViewFile(){

        return new ModelAndView("pages/ViewFile");


    }


    @RequestMapping("FileDown")
    @ResponseBody
//    文件下载
//    @ResponseBody
    public void  FileDown(Myfile myfile, HttpServletResponse response)throws IOException{


/*
        在前端请求文件下后，接受的myfile的信息后就会开始下载；
        但是移动端在文件传输了5kb左右时，就会停止，控制报错的内容就是myfile中的需要的内容不存在；
        调试时，在下载刚开始时信息是成功传递的，但是每5kb就会出现上述的错误；
        在写这段注释的时候，我想可能是断电续传的问题，每隔一个数据量就会向下载地址请求数据，
        因为我用的post传输，所以在向地址请求时，文件需要的信息并不会像get方式一样在地址中传输过去，
        所以就会出现得不到对相应信息的问题
*/

//        第一次信息传递成功时，将其保留下来以保证后面的下载不中断
        if(myfile.getFilepath() == null){
            myfile = DownFile;
        }else{
            DownFile = myfile;
        }


        System.out.println("—————FileDown—————");
        System.out.println(myfile.getFilepath());



        try{
            File file = new File(myfile.getFilepath());

//        将文件写入输入流
            FileInputStream fileInputStream = new FileInputStream(file);
            InputStream inputStream = new BufferedInputStream(fileInputStream);

//        清空response
            response.reset();
//        设置response的Header
            response.setCharacterEncoding("UTF-8");
//        Content-Disposition的作用：告知浏览器以何种方式显示响应返回的文件，用浏览器打开还是以附件的形式下载到本地保存
//        attachment表示以附件方式下载 inline表示在线打开 "Content-Disposition: inline; filename=文件名.mp3"
//        filename表示文件的默认名称，因为网络传输只支持URL编码的相关支付，因此需要将文件名URL编码后进行传输,前端收到后需要反编码才能获取到真正的名称
          response.addHeader("Content-Disposition","attachment;filename="+ URLEncoder.encode(myfile.getFilename(),"UTF-8"));
//        告知浏览器文件大小
            response.addHeader("Content-Length",""+file.length());

            OutputStream outputStream;
            outputStream = response.getOutputStream();

            response.setContentType("application/force-download");
            byte[] b = new byte[1024];
            int len;

            while((len = fileInputStream.read(b))>0){
                outputStream.write(b,0,len);
                System.out.println(len);
            }

            fileInputStream.close();



            System.out.println("传输结束");
        }catch (IOException e){

            e.printStackTrace();
        }

    }



    //    文件预览
    @RequestMapping("/filePreview")
    @ResponseBody
    public void filePreview(Myfile myfile,HttpServletResponse response) throws IOException{




    }





//    文件查询
    @ResponseBody
    @RequestMapping("/ViewFileAndSel")
    public R ViewFileAndSel(DownFile myfile,@RequestParam(defaultValue = "1") Integer page,
                            @RequestParam(defaultValue = "15")Integer limit) throws IOException{


        File file = new File(filepath);
        if (newMyfiletime == null){
            newMyfiletime = file.lastModified();
        }




        if(init == 1 || newMyfiletime != file.lastModified()){
            this.initialization();
            init = 0;
        }


        System.out.println("————ViewFileAndSel————");
        System.out.println(myfile.toString());
        System.out.println(page+"——"+limit);

        PageInfo<DownFile> pageInfo = myfileServiceImpl.SelDowunAllByName(myfile,page,limit);

        for (DownFile m: pageInfo.getList()) {
            System.out.println(m.getFilename());
        }

        System.out.println(pageInfo.getPageSize());

        Integer count = 11;

        return R.ok("成功", pageInfo.getList(),pageInfo.getTotal());
    }






//    //文件复制
//    Path1是原文件的文件夹路径
//    path2是原文件的路径
//    用以实现文件备份
    private void filecopy(String Path1,String filename) throws IOException {



        FileChannel InputFile = null;
        FileChannel OutputFile = null;

//        在要备份的文件目录下创建备份文件夹，然后将当前文件复制到备份文件夹中
        File mkdirs = new File(filepath+"\\备份");
        File file = new File(mkdirs.getPath()+"\\"+filename);

        System.out.println(filepath+"/备份/"+filename);


        try{

            mkdirs.mkdirs();

            if(!file.exists())
                file.createNewFile();

            InputFile = new FileInputStream(Path1).getChannel();
            OutputFile = new FileOutputStream(filepath+"\\备份\\"+filename).getChannel();

            OutputFile.transferFrom(InputFile,0,InputFile.size());
        }catch (IOException e){
            e.printStackTrace();
        }
        finally {
            InputFile.close();
            OutputFile.close();
        }
    }


}
